package uns.fit.gis.upload;

/**
 * Copyright by Christof Dallermassl
 * This program is free software and licensed under GPL.
 */

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;

import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import javax.microedition.lcdui.List;

//import com.sun.midp.io.Properties;
//import com.sun.midp.io.j2me.storage.File;
//import com.sun.perseus.platform.BufferedInputStream;


/**
 * Small java class that allows to upload gpx files to www.openstreetmap.org via its api call.
 * 
 * @author cdaller
 */
public class GpxUpload {
    public static final String API_VERSION = "0.6";
    private static final int BUFFER_SIZE = 65535;
    private static final String BASE64_ENC = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    private static final String BOUNDARY = "----------------------------d10f7aa230e8";
    private static final String LINE_END = "\r\n";
    
    public GpxUpload() {
        
    }
    
    public void upload(final String username, final String password, final String fileName, final String description, final String tags, final boolean isPublic, final String gpx) throws IOException {
        try {
            //String urlGpxName = URLEncoder.encode(gpxName.replaceAll("\\.;&?,/","_"), "UTF-8");
            String urlDesc = description;
            String urlTags = tags;
            String url = "http://www.openstreetmap.org/api/" + API_VERSION + "/gpx/create";
            System.err.println("url: " + url);
            HttpConnection con = (HttpConnection) Connector.open(url);
            con.setRequestMethod(HttpConnection.POST);
            con.setRequestProperty("Authorization", "Basic "+encodeBase64(username+":"+password));
            con.setRequestProperty("Content-Type", "multipart/form-data; boundary="+BOUNDARY);
            con.setRequestProperty("Connection", "close"); // counterpart of keep-alive
            con.setRequestProperty("Expect", "");
                        
            DataOutputStream out  =  con.openDataOutputStream();
//            DataOutputStream out  = new DataOutputStream(System.out);

            writeContentDispositionFile(out, "file", fileName, gpx);
            writeContentDisposition(out, "description", urlDesc);
            writeContentDisposition(out, "tags", urlTags);
            writeContentDisposition(out, "public", isPublic ? "1" : "0");
            
            out.write(("--" + BOUNDARY + "--" + LINE_END).getBytes());
            out.flush();
            
            int retCode = con.getResponseCode();
            String retMsg = con.getResponseMessage();
            System.err.println("\nreturn code: "+retCode + " " + retMsg);
            if (retCode != 200) {
                // Look for a detailed error message from the server
                if (con.getHeaderField("Error") != null)
                    retMsg += "\n" + con.getHeaderField("Error");
                con.close();
                throw new RuntimeException(retCode+" "+retMsg);
            }
            out.close();
            con.close();
            System.out.println(gpx);
        } catch(UnsupportedEncodingException ignore) {
        }   
    }
    
    /**
     * @param out
     * @param string
     * @param gpxFile
     * @throws IOException 
     */
    private void writeContentDispositionFile(DataOutputStream out, String name, String fileName, String gpx) throws IOException {
        out.write(("--" + BOUNDARY + LINE_END).getBytes());
        out.write(("Content-Disposition: form-data; name=\"" + name + "\"; filename=\"" + fileName + "\"" + LINE_END).getBytes());
        out.write(("Content-Type: application/octet-stream" + LINE_END).getBytes());
        out.write(LINE_END.getBytes());
        out.write(gpx.getBytes());
        out.write(LINE_END.getBytes());
    }

    /**
     * @param string
     * @param urlDesc
     * @throws IOException 
     */
    public void writeContentDisposition(DataOutputStream out, String name, String value) throws IOException {
        out.write(("--" + BOUNDARY + LINE_END).getBytes());
        out.write(("Content-Disposition: form-data; name=\"" + name + "\"" + LINE_END).getBytes());
        out.write(LINE_END.getBytes());
        out.write((value + LINE_END).getBytes());
    }

    /**
     * 
     */
    private static void printHelp() {
        System.out.println("Usage: java " + GpxUpload.class.getName() 
            + " <description> <tags> <files*>");
        System.out.println("Osm username and password can be defined as system properties" +
        		" by -Dusername=<username> and -Dpassword=<password> or if not given, josm's" +
        		"preference file is read.");
        System.out.println("Any messages are printed to stderror, only the filename that " +
        		"was sent successfully is printed to stdout, so you may use the output of this " +
        		"program in a pipe for other calls (like \"| xargs -i mv '{}' target_dir\"");
        
    }
    

    public static String encodeBase64(String s) {
      StringBuffer out = new StringBuffer();
      for (int i = 0; i < (s.length()+2)/3; ++i) {
        int l = Math.min(3, s.length()-i*3);
        String buf = s.substring(i*3, i*3+l);
        out.append(BASE64_ENC.charAt(buf.charAt(0)>>2));
        out.append(BASE64_ENC.charAt((buf.charAt(0) & 0x03) << 4 | (l==1?0:(buf.charAt(1) & 0xf0) >> 4)));
        out.append(l>1 ? BASE64_ENC.charAt((buf.charAt(1) & 0x0f) << 2 | (l==2 ? 0 : (buf.charAt(2) & 0xc0) >> 6)) : '=');
        out.append(l>2 ? BASE64_ENC.charAt(buf.charAt(2) & 0x3f) : '=');
      }
      return out.toString();
    }

}
